package com.yixing.tech.wmsjob;

import com.yixing.tech.common.autoline.domain.AGVRasterRequest;
import com.yixing.tech.common.autoline.domain.WCSResponse;
import com.yixing.tech.common.autoline.task.WCSConfig;
import com.yixing.tech.common.autoline.task.WCSTaskUtil;
import com.yixing.tech.common.hikservice.rcs.RCSConfig;
import com.yixing.tech.common.tcp.manage.EndpointManager;
import com.yixing.tech.common.tcp.manage.TcpClientEndpoint;
import com.yixing.tech.wcs.constant.DictName;
import com.yixing.tech.wcs.service.IBoxInteractionScheduleService;
import com.yixing.tech.wcs.service.ICRUDService;
import com.yixing.tech.wcs.service.ITaskService;
import com.yixing.tech.wcs.service.impl.CallbackService;
import com.yixing.tech.wcs.tcp.EndpointConfiguration;
import com.yixing.tech.wcs.tcp.InteractionConsumer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * WCS系统应用启动器
 * 负责初始化系统配置并启动各个业务线程
 */
@Component
@Slf4j
public class WCSAppRunner implements ApplicationRunner {

    @Resource
    ICRUDService crudService;

    @Resource
    ITaskService taskService;

    @Resource
    EndpointManager endpointManager;

    @Resource
    InteractionConsumer interactionConsumer;

    @Resource
    IBoxInteractionScheduleService boxInteractionScheduleService;

    // 存储系统运行期间的所有线程
    public static final Map<String, Thread> threadMap = new HashMap<>();

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 从数据库字典表中获取各类服务的IP和端口配置
        String rcsIp = crudService.queryDictValueByName(DictName.IpPort.RCS_IP);
        String rcsPort = crudService.queryDictValueByName(DictName.IpPort.RCS_PORT);
        String wcsIp = crudService.queryDictValueByName(DictName.IpPort.WCS_IP);
        String wcsPort = crudService.queryDictValueByName(DictName.IpPort.WCS_PORT);
        String deviceTransIp = crudService.queryDictValueByName(DictName.IpPort.TRANSPORTATION_IP);
        String deviceTransPort = crudService.queryDictValueByName(DictName.IpPort.TRANSPORTATION_PORT);

        // 设置RCS（机器人控制系统）配置
        RCSConfig.setConfig(rcsIp, Integer.valueOf(rcsPort));
        log.info("load ipPort config of rcs: {}", RCSConfig.getInstance());
        // 设置WCS配置
        WCSConfig.setConfig(wcsIp, Integer.parseInt(wcsPort));
        log.info("load ipPort config of wcs: {}", WCSConfig.getInstance());
        // 设置设备传输配置
        EndpointConfiguration.setDeviceAddrConfig(deviceTransIp, deviceTransPort);
        log.info("load ipPort config of deviceTransport:{}", EndpointConfiguration.getDeviceAddrConfig());

        // 连接输送线服务端程序，建立TCP通信连接
        TcpClientEndpoint clientEndpoint = endpointManager.createTcpClientEndpoint(EndpointConfiguration.getDeviceAddrConfig().getIp(),
                Integer.parseInt(EndpointConfiguration.getDeviceAddrConfig().getPort()), true, interactionConsumer.consumeFunc());
        EndpointConfiguration.setEndpointId(clientEndpoint.getEid());
        log.info("连接输送线服务端程序:{}", endpointManager.listEndpoints());

        // 创建主要任务处理线程，负责任务分解、资源分配、子任务启动和执行
        Thread thread = new Thread("任务处理线程") {
            @Override
            public void run() {
                while(true) {
                    try {
                        // 每5秒执行一次任务处理流程
                        Thread.sleep(5000);
                    } catch (Exception e) {
                        if(e instanceof InterruptedException) {
                            throw new RuntimeException("分解任务线程被打断");
                        }
                    }

                    try {
                        // 1. 将WMS下发的主任务分解为多个子任务
                        long startTime = System.currentTimeMillis();
                        taskService.decomposeTask();
                        log.info("分解任务耗时:{}", System.currentTimeMillis() - startTime);
                    } catch (Exception e) {
                        log.error("分解任务线程抛出异常:{}", e);
                    }

                    try {
                        // 2. 为子任务分配所需的资源（如库位等）
                        long startTime = System.currentTimeMillis();
                        taskService.allocateResourceForSubTask();
                        log.info("分配子任务资源耗时:{}", System.currentTimeMillis() - startTime);
                    } catch (Exception e) {
                        log.error("分配子任务资源抛出异常:{}", e);
                    }

                    try {
                        // 3. 启动已分配资源的子任务，下发给对应的硬件设备
                        long startTime = System.currentTimeMillis();
                        taskService.startUpSubTask();
                        log.info("启动子任务耗时:{}", System.currentTimeMillis() - startTime);
                    } catch (Exception e) {
                        log.error("启动子任务抛出异常:{}", e);
                    }

                    try {
                        // 4. 继续执行任务（处理依赖关系，推进任务链）
                        long startTime = System.currentTimeMillis();
                        taskService.continuePerformTask();
                        log.info("继续执行任务耗时:{}", System.currentTimeMillis() - startTime);
                    } catch (Exception e) {
                        log.error("继续执行任务抛出异常:{}", e);
                    }
                }
            }
        };
        thread.start();
        threadMap.put(thread.getName(), thread);

//        thread = new Thread("分配子任务资源线程") {
//            @Override
//            public void run() {
//                while(true) {
//                    try {
//                        Thread.sleep(5000);
//                        taskService.allocateResourceForSubTask();
//                    } catch (Exception e) {
//                        log.error("分配子任务资源线程抛出异常:{}", e);
//                        if(e instanceof InterruptedException) {
//                            throw new RuntimeException("分配子任务资源线程被打断");
//                        }
//                    }
//                }
//            }
//        };
//        thread.start();
//        threadMap.put(thread.getName(), thread);

//        thread = new Thread("启动子任务线程") {
//            @Override
//            public void run() {
//                while(true) {
//                    try {
//                        Thread.sleep(5000);
//                        taskService.startUpSubTask();
//                    } catch (Exception e) {
//                        log.error("启动子任务线程抛出异常:{}", e);
//                        if(e instanceof InterruptedException) {
//                            throw new RuntimeException("启动子任务线程被打断");
//                        }
//                    }
//                }
//            }
//        };
//        thread.start();
//        threadMap.put(thread.getName(), thread);

//        thread = new Thread("继续执行任务线程") {
//            @Override
//            public void run() {
//                while(true) {
//                    try {
//                        Thread.sleep(5000);
//                        taskService.continuePerformTask();
//                    } catch (Exception e) {
//                        log.error("继续执行任务线程抛出异常:{}", e);
//                        if(e instanceof InterruptedException) {
//                            throw new RuntimeException("继续执行任务线程被打断");
//                        }
//                    }
//                }
//            }
//        };
//        thread.start();
//        threadMap.put(thread.getName(), thread);



        // 创建请求WCS打开光栅的线程，用于AGV车辆通行控制
        thread = new Thread("请求wcs光栅打开线程") {
            @Override
            public void run() {
                while(true) {
                    try {
                        List<CompletableFuture<Void>> futureList = new ArrayList<>();
                        // 遍历所有需要打开光栅的AGV请求
                        for(Map.Entry<String, String> entry: CallbackService.rasterOpenMap.entrySet()) {
                            AGVRasterRequest request = new AGVRasterRequest();
                            request.setAGV_NO(entry.getKey());        // AGV编号
                            request.setOPTICAL_NO(entry.getValue());   // 光栅编号

                            // 异步请求打开光栅
                            futureList.add(CompletableFuture.runAsync(() -> {
                                try {
                                    WCSResponse response = WCSTaskUtil.openRaster(request);
                                    log.info("请求WCS打开光栅:request[{}],response[{}]", request, response);
                                } catch (Exception e) {
                                    log.error("请求打开光栅发生异常:{}", e);
                                }
                            }));
                        }

                        CompletableFuture[] arr = new CompletableFuture[futureList.size()];
                        for(int i=0; i<futureList.size(); ++i) {
                            arr[i] = futureList.get(i);
                        }
                        CompletableFuture<Void> a =  CompletableFuture.allOf(arr);
                        try {
                            a.get();  // 等待所有光栅打开请求完成
                        } catch (ExecutionException e) {
                            log.error("请求WCS打开光栅抛出异常:{}",e);
                        }

                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        thread.start();
        threadMap.put(thread.getName(), thread);

        // 创建请求WCS关闭光栅的线程，用于AGV车辆通行后的安全控制
        thread = new Thread("请求wcs光栅关闭线程") {
            @Override
            public void run() {
                while(true) {
                    try {
                        List<CompletableFuture<Void>> futureList = new ArrayList<>();
                        // 遍历所有需要关闭光栅的AGV请求
                        for(Map.Entry<String, String> entry: CallbackService.rasterCloseMap.entrySet()) {
                            AGVRasterRequest request = new AGVRasterRequest();
                            request.setAGV_NO(entry.getKey());        // AGV编号
                            request.setOPTICAL_NO(entry.getValue());   // 光栅编号

                            // 异步请求关闭光栅
                            futureList.add(CompletableFuture.runAsync(() -> {
                                try {
                                    WCSResponse response = WCSTaskUtil.closeRaster(request);
                                    log.info("请求WCS关闭光栅:request[{}],response[{}]", request, response);
                                } catch (Exception e) {
                                    log.error("请求关闭光栅发生异常:{}", e);
                                }
                            }));
                        }

                        CompletableFuture[] arr = new CompletableFuture[futureList.size()];
                        for(int i=0; i<futureList.size(); ++i) {
                            arr[i] = futureList.get(i);
                        }
                        CompletableFuture<Void> a =  CompletableFuture.allOf(arr);
                        try {
                            a.get();  // 等待所有光栅关闭请求完成
                        } catch (ExecutionException e) {
                            log.error("请求WCS关闭光栅抛出异常:{}",e);
                        }

                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        thread.start();
        threadMap.put(thread.getName(), thread);


        // 查询输送线设备状态的线程，用于实时监控设备状态
        thread = new Thread("查询输送线状态线程") {
            @Override
            public void run() {
                while(true) {
                    try {
                        // 查询设备的当前状态
                        boxInteractionScheduleService.queryDeviceState();
                        Thread.sleep(300);  // 每300ms查询一次
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        thread.start();
        threadMap.put(thread.getName(), thread);

        // 查询摄像头读取的料箱码的线程，用于识别箱号和位置
        thread = new Thread("查询读码头读取到的料箱码线程") {
            @Override
            public void run() {
                while(true) {
                    try {
                        // 查询摄像头读取到的料箱码信息
                        boxInteractionScheduleService.queryCameraPodCode();
                        Thread.sleep(500);  // 每500ms查询一次
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        thread.start();
        threadMap.put(thread.getName(), thread);

        // 通知设备料箱放下完成的线程，用于与输送线设备交互
        thread = new Thread("通知设备料箱放下完成线程") {
            @Override
            public void run() {
                while(true) {
                    try {
                        // 通知设备料箱放下动作已完成
                        boxInteractionScheduleService.notifyBoxPutDownFin();
                        Thread.sleep(300);  // 每300ms检查一次
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        thread.start();
        threadMap.put(thread.getName(), thread);

        // 通知设备料箱处理完成的线程，用于与输送线设备交互
        thread = new Thread("通知设备料箱处理完成线程") {
            @Override
            public void run() {
                while(true) {
                    try {
                        // 通知设备料箱分拣等处理已完成
                        boxInteractionScheduleService.notifyBoxHandlingFin();
                        Thread.sleep(300);  // 每300ms检查一次
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        thread.start();
        threadMap.put(thread.getName(), thread);

        // 通知设备料箱取出完成的线程，用于与输送线设备交互
        thread = new Thread("通知设备料箱取出完成线程") {
            @Override
            public void run() {
                while(true) {
                    try {
                        // 通知设备料箱取出动作已完成
                        boxInteractionScheduleService.notifyBoxTakeOutFin();
                        Thread.sleep(300);  // 每300ms检查一次
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        thread.start();
        threadMap.put(thread.getName(), thread);

        // 更新料箱完成处理状态的线程，用于更新系统内料箱状态
        thread = new Thread("更新料箱完成处理状态线程") {
            @Override
            public void run() {
                while(true) {
                    try {
                        // 检查并更新料箱的处理完成状态
                        boxInteractionScheduleService.boxHandlingFin();
                        Thread.sleep(2000);  // 每2秒检查一次
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        thread.start();
        threadMap.put(thread.getName(), thread);
    }

}
